package top.byteio.common.s3.strategy;

import cn.hutool.core.util.IdUtil;
import cn.hutool.crypto.SecureUtil;
import lombok.extern.slf4j.Slf4j;
import top.byteio.common.core.constants.DateConstants;
import top.byteio.common.core.crypto.Base64;
import top.byteio.common.s3.exception.StorageKeyGenerateException;
import top.byteio.common.s3.utils.StorageUtils;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

@Slf4j
public class DefaultStorageStrategy implements StorageKeyStrategy{

    @Override
    public String generate(String filename) {
        // 入参校验
        if (filename == null || filename.trim().isEmpty()) {
            throw new IllegalArgumentException("文件名不能为空");
        }
        String trimmedFilename = filename.trim();

        // 生成日期路径（如：2023/10/05）
        String datePath = LocalDateTime.now()
                .format(DateTimeFormatter.ofPattern(DateConstants.YEAR_MONTH_DAY_Slash));

        // 生成唯一标识与哈希值
        String uuid = IdUtil.fastSimpleUUID();
        String filenameHash = SecureUtil.md5(trimmedFilename);

        // 解析文件名与扩展名
        int extSeparatorIndex = trimmedFilename.lastIndexOf(".");
        String baseName = extSeparatorIndex > 0 ?
                trimmedFilename.substring(0, extSeparatorIndex) :
                trimmedFilename;
        String fileExt = StorageUtils.getObjectType(trimmedFilename);

        // 对基础文件名进行Base64编码（避免特殊字符）
        String encodedBaseName = Base64.encode(baseName);

        // 构造最终存储Key（格式：日期/uuid#哈希#编码文件名.扩展名）
        return String.format("%s/%s#%s#%s.%s",
                datePath, uuid, filenameHash, encodedBaseName, fileExt);
    }

    @Override
    public String restore(String key) {
        // 入参校验
        if (key == null || key.trim().isEmpty()) {
            log.warn("恢复文件名失败，key为空");
            throw new IllegalArgumentException("key不能为空");
        }
        String trimmedKey = key.trim();

        // 解析Key结构（日期/uuid#哈希#编码文件名.扩展名）
        int lastHashIndex = trimmedKey.lastIndexOf("#");
        int extIndex = trimmedKey.lastIndexOf(".");

        // 格式校验
        if (lastHashIndex == -1 || extIndex == -1 || extIndex <= lastHashIndex) {
            log.error("恢复文件名失败，key格式错误: {}", trimmedKey);
            throw new StorageKeyGenerateException("key格式错误，无法解析");
        }

        // 提取并解码基础文件名
        String encodedBaseName = trimmedKey.substring(lastHashIndex + 1, extIndex);
        String fileExt = trimmedKey.substring(extIndex + 1);

        try {
            String decodedBaseName = Base64.decode(encodedBaseName);
            return decodedBaseName + "." + fileExt;
        } catch (Exception e) {
            log.error("Base64解码失败，encodedBaseName: {}", encodedBaseName, e);
            throw new StorageKeyGenerateException("文件名解码失败", e);
        }
    }
}
